namespace MetaProperties.Collections
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// An observable keyed collection.
    /// </summary>
    /// <typeparam name="KeyT">The type of the key for the elements in the list.</typeparam>
    /// <typeparam name="ItemT">The type of the elements in the list.</typeparam>
    public interface IObservableKeyedCollection<KeyT, ItemT> : IObservableList<ItemT>
    {
        /// <summary>
        /// Gets the item with the specified key.
        /// </summary>
        /// <param name="key">The key of the item.</param>
        /// <value>The item with the specified key.</value>
        ItemT this[KeyT key]
        {
            get;
        }

        /// <summary>
        /// Returns the items as an array.
        /// </summary>
        /// <returns>The items as an array.</returns>
        ItemT[] ToArray();

        /// <summary>
        /// Adds the specified items to the collection.
        /// </summary>
        /// <param name="items">The items to add.</param>
        void AddRange(IEnumerable<ItemT> items);

        /// <summary>
        /// Determines whether the collection contains an item with the specified key.
        /// </summary>
        /// <param name="key">The key of the item.</param>
        /// <returns>
        ///  <c>true</c> if an item with the specified key exists; otherwise, <c>false</c>.
        /// </returns>
        bool Contains(KeyT key);

        /// <summary>
        /// Gets the index of the item with the speficied key.
        /// </summary>
        /// <param name="key">The key of the item.</param>
        /// <returns>The index of the item with the speficied key.</returns>
        int IndexOf(KeyT key);

        /// <summary>
        /// Tries to the get the item with the speficied key.
        /// </summary>
        /// <param name="key">The key of the item.</param>
        /// <param name="value">The value.</param>
        /// <returns>True if the item exists, false otherwise.</returns>
        bool TryGetValue(KeyT key, out ItemT value);

        /// <summary>
        /// Removes the item with the specified key.
        /// </summary>
        /// <param name="key">The key of the item.</param>
        /// <returns>True if an item was removed, false otherwise.</returns>
        bool Remove(KeyT key);
    }
}